package com.usian.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.usian.IDUtils;
import com.usian.PageResult;
import com.usian.mapper.*;
import com.usian.pojo.*;
import com.usian.redis.RedisClient;
import com.usian.service.ItemService;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class ItemServiceImpl implements ItemService {

    @Autowired
    private TbItemMapper tbItemMapper;

    @Autowired
    private TbItemDescMapper tbItemDescMapper;

    @Autowired
    private TbItemParamItemMapper tbItemParamItemMapper;

    @Autowired
    private TbItemCatMapper tbItemCatMapper;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private RedisClient redisClient;

    @Autowired
    private TbOrderItemMapper tbOrderItemMapper;

    @Value("${ITEM_INFO}")
    private String ITEM_INFO;

    @Value("${BASE}")
    private String BASE;

    @Value("${DESC}")
    private String DESC;

    @Value("${PARAM}")
    private String PARAM;

    @Value("${ITEM_INFO_EXPIRE}")
    private Integer ITEM_INFO_EXPIRE;

    @Override
    public TbItem findItemById(Long id) {
//        查询先查redis没有在查库
        TbItem tbItem = (TbItem) redisClient.get(ITEM_INFO + ":" + id.toString() + ":" + BASE);
        if (tbItem!=null){
            return tbItem;
        }
//        防止redis的缓存击穿redis分布式锁setnx
        if (redisClient.setnx(ITEM_INFO + ":" + id.toString() + ":" + BASE+":NX","lock",30)){
//            抢占redis资源
            //        防止redis缓存穿透
            tbItem = tbItemMapper.selectByPrimaryKey(id);
//        数据库没有数据在缓存中存入空值
            if (tbItem==null) {
                //        写入redis
                redisClient.set(ITEM_INFO + ":" + id.toString() + ":" + BASE, new TbItem(1L,"redis数据为空"));
                redisClient.expire(ITEM_INFO + ":" + id.toString() + ":" + BASE, 30);
            }else {
//        写入redis
                redisClient.set(ITEM_INFO + ":" + id.toString() + ":" + BASE, tbItem);
                redisClient.expire(ITEM_INFO + ":" + id.toString() + ":" + BASE, ITEM_INFO_EXPIRE);
            }
            redisClient.del(ITEM_INFO + ":" + id.toString() + ":" + BASE+":NX");
        }

            return tbItem;
    }
    /**
     * 查询商品列表
     *
     * @param page
     * @param rows
     * @return
     */
    @Override
    public PageResult selectTbItemAllByPage(Integer page, Integer rows) {
        PageHelper.startPage(page,rows);
        TbItemExample example = new TbItemExample();
        TbItemExample.Criteria criteria = example.createCriteria();
        criteria.andStatusEqualTo((byte)1);
        List<TbItem> itemList = tbItemMapper.selectByExample(example);
        PageInfo<TbItem> pageInfo = new PageInfo<>(itemList);
        PageResult pageResult = new PageResult();
        pageResult.setPageIndex(pageInfo.getPageNum());
        pageResult.setTotalPage(pageInfo.getPages());
        pageResult.setResult(pageInfo.getList());
        return pageResult;
    }

//添加商品
    @Override
    public Integer insertTbItem(TbItem tbItem, String desc, String itemParams) {
//        保存三张表
//        多表保存的时候先保存主表
//        tb_item
        long itemId = IDUtils.genItemId();
        tbItem.setId(itemId);
        tbItem.setStatus((byte) 1);
        tbItem.setCreated(new Date());
        tbItem.setUpdated(new Date());
        int insert = tbItemMapper.insertSelective(tbItem);
//        tb_item_desc
        TbItemDesc tbItemDesc = new TbItemDesc();
        tbItemDesc.setItemId(itemId);
        tbItemDesc.setItemDesc(desc);
        tbItemDesc.setCreated(new Date());
        tbItemDesc.setUpdated(new Date());
        int insert1 = tbItemDescMapper.insertSelective(tbItemDesc);
//        tb_item_param_item
        TbItemParamItem tbItemParamItem = new TbItemParamItem();
        tbItemParamItem.setItemId(itemId);
        tbItemParamItem.setCreated(new Date());
        tbItemParamItem.setUpdated(new Date());
        tbItemParamItem.setParamData(itemParams);
        int insert2 = tbItemParamItemMapper.insertSelective(tbItemParamItem);

        //        同步数据到es  发送MQ消息  convertAndSend (1：交换机exchange，2：路由规则routingkey，3：消息内容meg)
        amqpTemplate.convertAndSend("item_exchange", "item.add", itemId);   //skuId
//        添加redis
        if(insert+insert1+insert2==3) {
            redisClient.set(ITEM_INFO + ":" + tbItem.getId().toString() + ":" + BASE, tbItem);
            redisClient.set(ITEM_INFO + ":" + tbItem.getId().toString() + ":" + DESC, tbItemDesc);
            redisClient.set(ITEM_INFO + ":" + tbItem.getId().toString() + ":" + PARAM,tbItemParamItem);
        }
        return insert+insert1+insert2;
    }

//    商品信息回显
    @Override
    public Map<String, Object> preUpdateItem(Long itemId) {
        HashMap<String, Object> hashMap = new HashMap<>();
//        item
        TbItem tbItem = tbItemMapper.selectByPrimaryKey(itemId);
        hashMap.put("item", tbItem);
//        itemcat name
        TbItemCat tbItemCat = tbItemCatMapper.selectByPrimaryKey(tbItem.getCid());
        hashMap.put("itemCat", tbItemCat.getName());
//        itemDesc
        TbItemDesc tbItemDesc = tbItemDescMapper.selectByPrimaryKey(itemId);
        hashMap.put("itemDesc", tbItemDesc.getItemDesc());
//        itemParamitem
        TbItemParamItemExample example = new TbItemParamItemExample();
        TbItemParamItemExample.Criteria criteria = example.createCriteria();
        criteria.andItemIdEqualTo(itemId);
        List<TbItemParamItem> paramItemList = tbItemParamItemMapper.selectByExampleWithBLOBs(example);
        if (paramItemList.size()>0) {
            hashMap.put("itemParamItem", paramItemList.get(0).getParamData());
        }

        return hashMap;
    }

    @Override
    public Integer updateTbItem(TbItem tbItem, String desc, String itemParams) {
        //        保存三张表
//        多表保存的时候先保存主表
//        tb_item
        Long itemId = tbItem.getId();
        tbItem.setStatus((byte) 1);
//        tbItem.setCreated(new Date());
        tbItem.setUpdated(new Date());
        int insert = tbItemMapper.updateByPrimaryKeySelective(tbItem);
//        tb_item_desc
        TbItemDesc tbItemDesc = new TbItemDesc();
        tbItemDesc.setItemId(itemId);
        tbItemDesc.setItemDesc(desc);
//        tbItemDesc.setCreated(new Date());
        tbItemDesc.setUpdated(new Date());
        int insert1 = tbItemDescMapper.updateByPrimaryKeySelective(tbItemDesc);
//        tb_item_param_item
        TbItemParamItem tbItemParamItem = new TbItemParamItem();
        tbItemParamItem.setItemId(itemId);
//        tbItemParamItem.setCreated(new Date());
        tbItemParamItem.setUpdated(new Date());
        tbItemParamItem.setParamData(itemParams);
        TbItemParamItemExample paramItemExample = new TbItemParamItemExample();
        TbItemParamItemExample.Criteria criteria = paramItemExample.createCriteria();
        criteria.andItemIdEqualTo(itemId);
        int insert2 = tbItemParamItemMapper.updateByExampleSelective(tbItemParamItem,paramItemExample);

//        同步数据到es  发送MQ消息  convertAndSend (1：交换机exchange，2：路由规则routingkey，3：消息内容meg)
        amqpTemplate.convertAndSend("item_exchange", "item.update", tbItem.getId());
        //        添加redis
        if(insert+insert1+insert2==3) {
            redisClient.set(ITEM_INFO + ":" + tbItem.getId().toString() + ":" + BASE, tbItem);
            redisClient.set(ITEM_INFO + ":" + tbItem.getId().toString() + ":" + DESC, tbItemDesc);
            redisClient.set(ITEM_INFO + ":" + tbItem.getId().toString() + ":" + PARAM,tbItemParamItem);
        }
        return insert+insert1+insert2;
    }

    @Override
    public Integer deleteItemById(Long itemId) {
//        删除TbItemParamItem
        TbItemParamItemExample example = new TbItemParamItemExample();
        TbItemParamItemExample.Criteria criteria = example.createCriteria();
        criteria.andItemIdEqualTo(itemId);
        int result1 = tbItemParamItemMapper.deleteByExample(example);
        //        删除TbItemDesc
        int result2 = tbItemDescMapper.deleteByPrimaryKey(itemId);
//        删除TbItem
        TbItem tbItem = new TbItem();
        tbItem.setId(itemId);
        tbItem.setStatus((byte) 3);
        tbItem.setUpdated(new Date());
        int result3 = tbItemMapper.updateByPrimaryKeySelective(tbItem);
        //        添加redis
        if(result1+result2+result3==3) {
            redisClient.del(ITEM_INFO + ":" + itemId.toString() + ":" + BASE);
            redisClient.del(ITEM_INFO + ":" + tbItem.getId().toString() + ":" + DESC);
            redisClient.del(ITEM_INFO + ":" + tbItem.getId().toString() + ":" + PARAM);
        }
        return result1+result2+result3;
    }

    /**
     * 查询商品详情
     *
     * @param itemId
     * @return
     */
    @Override
    public TbItemDesc selectItemDescByItemId(Long itemId) {
//        先查redis  没有在查数据库
        TbItemDesc tbItemDesc = (TbItemDesc) redisClient.get(ITEM_INFO+":"+itemId.toString()+":"+DESC);
        if (tbItemDesc!=null){
            return tbItemDesc;
        }
//        防止redis缓存击穿
        if (redisClient.setnx(ITEM_INFO+":"+itemId.toString()+":"+DESC+":NX","lock",30)) {
            //        查询数据
            tbItemDesc = tbItemDescMapper.selectByPrimaryKey(itemId);
            if (tbItemDesc==null) {
                //        添加redis空数据
                redisClient.set(ITEM_INFO+":"+itemId.toString()+":"+DESC,new TbItemDesc(1L,"redis空值"));
                redisClient.expire(ITEM_INFO+":"+itemId.toString()+":"+DESC,30);
            }else {
                //        添加redis
                redisClient.set(ITEM_INFO+":"+itemId.toString()+":"+DESC,tbItemDesc);
                redisClient.expire(ITEM_INFO+":"+itemId.toString()+":"+DESC,ITEM_INFO_EXPIRE);
            }
//            释放redis锁
            redisClient.del(ITEM_INFO+":"+itemId.toString()+":"+DESC+":NX");
        }
        return tbItemDesc;
    }

    /**
     *修改商品库存数量
     *
     * @param orderId
     * @return
     */
    @Override
    public Integer updateTbItemByOrderId(String orderId) {
        TbOrderItemExample tbOrderItemExample = new TbOrderItemExample();
        TbOrderItemExample.Criteria criteria = tbOrderItemExample.createCriteria();
        criteria.andOrderIdEqualTo(orderId);
        List<TbOrderItem> orderItemList = tbOrderItemMapper.selectByExample(tbOrderItemExample);
        Integer result = 0;
        for (TbOrderItem tbOrderItem : orderItemList) {
            TbItem tbItem = tbItemMapper.selectByPrimaryKey(Long.valueOf(tbOrderItem.getItemId()));
            tbItem.setNum(tbItem.getNum()-tbOrderItem.getNum());
            result += tbItemMapper.updateByPrimaryKey(tbItem);
        }
        return result;
    }
}
